#include "windowJuego.h"
#include "singleSocket.h"
#include <string>
#include "../Common/Movimiento.h"
#include "windowInit.h"
#include "windowRooms.h"
#include <sstream>
#include "sdlTextImage.h"
#include "../Common/ImagenJson.h"
#include "user.h"

#include <iostream>

using std::string;

Uint32 timerCallback(Uint32 intervalo, void* param){
	if (*(bool*)param){ //if noMover
		SDL_Event event;
    	SDL_UserEvent userevent;
		userevent.type = SDL_USEREVENT;
		userevent.code = 0;
		userevent.data1 = NULL;
		userevent.data2 = NULL;
		event.type = SDL_USEREVENT;
		event.user = userevent;
		SDL_PushEvent(&event);
	}
	return intervalo;
}


windowJuego::windowJuego(sdlScreen& screen): window::window(screen){
	Json::Value root;
	singleSocket* socket = singleSocket::getInstance();
	User* user = User::getInstance();
	socket->recibir(root,user->getPass());
	string accion = root["Accion"].asString();
	if (accion == "Imagen fondo personalizada"){
		ImagenJson aImgJson;
		aImgJson.setJson(root["Binario Fondo"]);
		std::stringstream path;
		path<<"fondoJuegoPerson"<<user->getName()<<".png";
		aImgJson.getImagenToPath(path.str());
		this->tablero.setBackground(path.str());
	}
	root.clear();
	socket->recibir(root,user->getPass());
	accion = root["Accion"].asString();
	if (accion == "Imagen agujero personalizada"){
		ImagenJson aImgJson;
		aImgJson.setJson(root["Binario agujero"]);
		aImgJson.getImagenToPath("agujeroPerson.gif");
		this->tablero.setImgBloque("agujeroPerson.gif");
	}
	root.clear();
	socket->recibir(root,user->getPass());
	accion = root["Accion"].asString();
	if (accion == "Mostrar tablero"){
		Json::Value rootTablero = root["Tablero"];
		this->tablero.actualizar(rootTablero);
	}
	this->background.load("backgroundWelcome.png");
	this->par1Selected = false;
	this->par2Selected = false;
	this->noMover = false;
	this->receptor = new ReceptorMovs(socket,this->noMover,this->mut,this->condVar);
	socket->recibir(root,user->getPass());
	accion = root["Accion"].asString();
	if (!this->receptor->isRunning()){
		this->receptor->start();
	}
	this->timer = SDL_AddTimer(2,timerCallback,&this->noMover);
	this->sndBotClick.load("botClicked.wav");
	this->sndMatch.load("vanishSound.wav");
}

void windowJuego::show(){
	this->screen.applySurface(0,0,this->background);
	this->tablero.dibujar(screen,200,0);
	this->screen.refresh();
}

window* windowJuego::actualizarTablero(Json::Value& root){

	string accion = root["Accion"].asString();
	unsigned maxScore = root["Maximo score"].asUInt();
	while (accion == "Mostrar tablero"){
		Json::Value rootTablero = root["Tablero"];
		this->tablero.actualizar(rootTablero);
		this->show();
		if (this->tablero.getEstado() == bajando){
			this->sndMatch.play();
			SDL_Delay(50);
		}
		this->mut.lock();
		if (!this->receptor->hayDatos()){
			this->condVar.wait(this->mut);
			//std::cout<<"delay"<<std::endl;
		}
		this->receptor->getDato(root);
		this->mut.unlock();
		accion = root["Accion"].asString();
		SDL_Delay(200); //Delay para que no vaya tan rápido el juego
	}
	//std::cout<<"actualizar "<<accion<<std::endl;
	if (accion == "Mostrar puntajes"){
		this->mostrarScore(root,maxScore);
	}
	this->mut.lock();
	if (!this->receptor->hayDatos()){
		this->condVar.wait(this->mut);
		//std::cout<<"delay"<<std::endl;
	}
	this->receptor->getDato(root);
	this->mut.unlock();

	accion = root["Accion"].asString();
	if (accion == "Enviar movimiento"){
		this->noMover = false;
	}
	window* ventana = NULL;
	if (accion == "Fin"){
		ventana = this->handleFin(root);
	}
	return ventana;
}

void windowJuego::mostrarScore(Json::Value& json,unsigned maxScore){
	unsigned cantDeJugadores = json["CantDeJugadores"].asUInt();
	sdlFont fuente("font.ttf", 20);
	int actWidth = 0;
	int actHeight = 0;
	sdlTextImage textoMostrar;
	textoMostrar.renderText(fuente,"Puntajes: ",ColorTextImage::amarillo);
	this->screen.applySurface(actWidth,actHeight,textoMostrar);
	actHeight += 30;
	std::stringstream auxTxt;
	auxTxt <<"Objetivo: "<<maxScore;
	textoMostrar.renderText(fuente,auxTxt.str(),ColorTextImage::amarillo);
	this->screen.applySurface(actWidth,actHeight,textoMostrar);
	actHeight += 30;
	for(unsigned i = 0; i < cantDeJugadores; i++){
		std::stringstream texto;
		texto << json["Jugadores"][i]["Nombre"].asString() << ": ";
		texto << json["Jugadores"][i]["Puntaje"].asUInt();
		textoMostrar.renderText(fuente,texto.str(),ColorTextImage::blanco);
		this->screen.applySurface(actWidth,actHeight,textoMostrar);
		actHeight += 30;
	}
	this->screen.refresh();
}

bool reloguear(){
	User* user =  User::getInstance();
	Json::Value root;
	root["Opcion"] = "Iniciar sesion";
	root["Nombre de usuario"] = user->getName();
	root["Contrasenia"] = user->getPass();

	singleSocket::eliminar();
	singleSocket* socket = singleSocket::getInstance();
	if (!socket->conectado()){socket->conectar();}
	socket->enviar(root);

	Json::Value rootRespuesta;
	socket->recibir(rootRespuesta);
	string resultado = rootRespuesta.get("Respuesta", "").asString();
	if(resultado != "Ingreso exitoso"){return false;}
	return true;
}

window* windowJuego::handleFin(Json::Value& json){
	string ganador = json["Ganador"].asString();
	sdlImage fondo("fondoGanador.gif");
	int actWidth = (this->screen.width() - fondo.width())/2;
	int actHeight = (this->screen.height() - fondo.height())/2;
	this->screen.applySurface(actWidth,actHeight,fondo);
	sdlTextImage winner;
	sdlFont fuente("font.ttf", 40);
	if (ganador == "Juego perdido"){
		winner.renderText(fuente,"         ",ColorTextImage::rojo);
		actHeight -= 75;
	} else {
		winner.renderText(fuente,"El ganador es: ",ColorTextImage::rojo);
	}
	actWidth += (fondo.width() - winner.width())/2;
	actHeight += 25;
	this->screen.applySurface(actWidth,actHeight,winner);
	winner.renderText(fuente,ganador+"!",ColorTextImage::rojo);
	actWidth = (this->screen.width() - fondo.width())/2;
	actWidth += (fondo.width() - winner.width())/2;
	actWidth -= 10;
	actHeight+=150;
	this->screen.applySurface(actWidth,actHeight,winner);
	this->screen.refresh();
	SDL_Delay(2500);
	window* ventana = NULL;
	this->receptor->finish();
	this->receptor->join();
	
	if (reloguear()){
		ventana = new windowRooms(this->screen);	
	} else {
		ventana = new windowInit(this->screen);
	}
	return ventana;
}

window* windowJuego::handleRecepcion(){
	Json::Value root;
	this->receptor->getDato(root);
	string accion = root["Accion"].asString();
	window* ventana = NULL;
	//std::cout<<accion<<std::endl;
	if (accion == "Fin"){
		ventana = this->handleFin(root);
	} else if (accion == "Mostrar tablero"){
		ventana = this->actualizarTablero(root);
	}
	return ventana;
}

void windowJuego::enviarMov(){
	singleSocket* socket = singleSocket::getInstance();
	Movimiento mov(par1.second, par1.first, par2.second, par2.first);
	User* user = User::getInstance();
	socket->enviar(mov.getJson(),user->getPass());
}

bool windowJuego::handleEvent(const SDL_Event& event, window*& win){
	win = NULL;
	bool b = false;
	if (this->receptor->hayDatos()){
		//std::cout<<"No mover"<<std::endl;
		this->par1Selected = false;
		this->par2Selected = false;
		win = this->handleRecepcion();
		return true;
	}
	if (event.type == SDL_MOUSEBUTTONDOWN){
		if (event.button.button == SDL_BUTTON_LEFT){
			this->sndBotClick.play();
			unsigned x,y;
			if(this->tablero.handleEvent(event,x,y)){
				if (!this->par1Selected){
					this->par1 = std::make_pair(x,y);
					this->par1Selected = true;
				} else if (!this->par2Selected){
					this->par2 = std::make_pair(x,y);
					this->par2Selected = true;
					this->enviarMov();
					this->par1Selected = false;
					this->par2Selected = false;
				}
				b = true;
			}
			//SDL_Delay(150); // Vale la espera?
		} else if (event.button.button == SDL_BUTTON_RIGHT){
			this->par1Selected = false;
			this->par2Selected = false;
			b = true;
		}
	}
	return b;
}

windowJuego::~windowJuego(){
	SDL_RemoveTimer(this->timer);
	//this->receptor->exit();
}
